package com.baosight.risk.base.controller;

import com.baosight.risk.api.xtdc.XtdcAttachService;
import com.baosight.risk.api.xtdc.XtdcDirectoryService;
import com.baosight.risk.base.redis.BaseRedis;
import com.baosight.risk.common.bean.BeanUtils;
import com.baosight.risk.common.file.FileManager;
import com.baosight.risk.common.result.AjaxResult;
import com.baosight.risk.common.utils.FileUtils;
import com.baosight.risk.common.utils.ReadProperties;
import com.baosight.risk.common.utils.StringUtils;
import com.baosight.risk.common.utils.ZipUtils;
import com.baosight.risk.mapper.xtdc.XtdcAttachMapper;
import com.baosight.risk.service.xtdc.entity.XtdcAttach;
import com.baosight.risk.service.xtdc.entity.XtdcDirectory;
import com.baosight.risk.service.xtdc.vo.DirVO;
import com.baosight.risk.service.xtdc.vo.ResourceVO;
import com.google.common.io.Files;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

import static com.baosight.risk.common.utils.ShiroUtils.getUser;

/**
 * 通用请求处理
 *
 * @author duanyongqiang
 */
@RestController
@Api(value = "文件下载", description = "文件下载", produces = MediaType.APPLICATION_JSON)
public class CommonController{
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private BaseRedis redisLock;
    @Autowired
    private FileManager fileManager;

    @Autowired
    private XtdcAttachService xtdcAttachService;

    @Autowired
    private XtdcAttachMapper attachMapper;

    @Autowired
    private XtdcDirectoryService directoryService;

    @GetMapping("common/download")
    @ApiOperation("文件下载")
    public void fileDownload(String fileName, String relativePath, String businessCode, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
        try {
            //带上文件id
            String fileId = request.getParameter("id");
            if (StringUtils.isNotEmpty(fileId)) {
                XtdcAttach xtdcAttach = attachMapper.selectById(fileId);
                String filePath = xtdcAttach.getFilePath();
                response.setCharacterEncoding("utf-8");
                response.setContentType("multipart/form-data");
                response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
                FileUtils.writeBytes(filePath, response.getOutputStream());
                if (delete != null && delete) {
                    FileUtils.deleteFile(filePath);
                }
            } else {
                String filePath = ReadProperties.getValueString("projectServerFilePath");
                if (StringUtils.isNotEmpty(relativePath)) {
                    filePath = filePath + "/" + relativePath + "/";
                }
                //兼容老代码（待删除）
                if (StringUtils.isNotEmpty(businessCode)) {
                    FileManager.Config config = fileManager.getConfig();
                    config.setBusinessCode(businessCode);
                    String dir = fileManager.generateDir(config);
                    filePath = dir;
                }

                filePath += fileName;
                response.setCharacterEncoding("utf-8");
                response.setContentType("multipart/form-data");
                response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
                FileUtils.writeBytes(filePath, response.getOutputStream());
                if (delete != null && delete) {
                    FileUtils.deleteFile(filePath);
                }
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }

    }

    /*@GetMapping("common/downloadRisk")
    @ApiOperation("文件下载")
    public void fileRiskDownload(String fileName, String relativePath, String businessCode, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        String realFileName = System.currentTimeMillis() + fileName;
        try {
            //带上文件id
            String fileId = request.getParameter("id");
            if (StringUtils.isNotEmpty(fileId)) {
                XtdcAttach xtdcAttach = attachMapper.selectById(fileId);
                String filePath = xtdcAttach.getFilePath();
                response.setCharacterEncoding("utf-8");
                response.setContentType("multipart/form-data");
                response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
                FileUtils.writeBytes(filePath, response.getOutputStream());
                if (delete != null && delete) {
                    FileUtils.deleteFile(filePath);
                }
            } else {
                String filePath = ReadProperties.getValueString("projectServerFilePath");
                if (StringUtils.isNotEmpty(relativePath)) {
                    filePath = filePath + "/" + relativePath + "/";
                }
                //兼容老代码（待删除）
                if (StringUtils.isNotEmpty(businessCode)) {
                    FileManager.Config config = fileManager.getConfig();
                    config.setBusinessCode(businessCode);
                    String dir = fileManager.generateDir(config);
                    filePath = dir;
                }

                filePath += fileName;
                response.setCharacterEncoding("utf-8");
                response.setContentType("multipart/form-data");
                response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
                FileUtils.writeBytes(filePath, response.getOutputStream());
                if (delete != null && delete) {
                    FileUtils.deleteFile(filePath);
                }
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }

    }*/
    public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE")) {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        } else if (agent.contains("Chrome")) {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        } else {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }

    @PostMapping("common/upload")
    @ApiOperation("文件上传")
    public AjaxResult fileUpload(HttpServletRequest request) {
        //转换request
        // 使用Spring的MultipartResolver进行解析
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        commonsMultipartResolver.setDefaultEncoding("UTF-8");
        // 确保请求是multipart类型
        if (!commonsMultipartResolver.isMultipart(request)) {
            return AjaxResult.error("请求不是multipart类型");
        }
        MultipartHttpServletRequest multipartRequest = commonsMultipartResolver.resolveMultipart(request);
        if (multipartRequest == null) {
            return AjaxResult.error("文件解析失败");
        }
        //获取页面传参
        //业务id
        String sourceGuid = multipartRequest.getParameter("sourceGuid");
        //业务表的表名
        String sourceModel = multipartRequest.getParameter("sourceModel");
        //是否覆盖之前的文件
        boolean replace = Boolean.valueOf(multipartRequest.getParameter("replace"));
        if (StringUtils.isEmpty(sourceGuid) || StringUtils.isEmpty(sourceModel)) {
            return AjaxResult.error("缺少必传参数！");
        }

        if (replace) {
            xtdcAttachService.deleteFilesBySourceAndModel(sourceGuid, sourceModel);
        }

        List<Map<String, Object>> list = new ArrayList<>();
        // 检查是否是multipart请求
        if (!ServletFileUpload.isMultipartContent(request)) {
            return AjaxResult.error("不是有效的文件上传请求");
        }

        //获取附件
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        if (fileMap.size() == 0){
            fileMap=((DefaultMultipartHttpServletRequest) request).getFileMap();
        }
        try {
            for (String key : fileMap.keySet()) {
                MultipartFile multipartFile = fileMap.get(key);
                InputStream inputStream = multipartFile.getInputStream();
                String filename = multipartFile.getOriginalFilename();
                long fileSize = multipartFile.getSize();

                filename = UUID.randomUUID().toString() + "_" + filename;

                String businessCode = sourceModel;
                if (sourceModel.startsWith("宝钢股份")) {
                    businessCode = sourceGuid;
                }

                FileManager.Config config = fileManager.getConfig();
                config.setInputStream(inputStream);
                config.setBusinessCode(businessCode);
                config.setFilename(filename);

                //生成目录
                String dir = fileManager.generateDir(config);
                String filepath = dir + filename;
                String fileType = fileManager.getFileType(filename);
                String relativePath = filepath.substring(filepath.indexOf(businessCode));
                //保存文件到磁盘
                multipartFile.transferTo(new File(filepath));

                //存入数据库
                XtdcAttach attach = (XtdcAttach) BeanUtils.initBean(new XtdcAttach());
                attach.setFileName(filename);
                attach.setFilePath(filepath);
                attach.setFileSize(fileSize);
                attach.setFileType(fileType);
                attach.setExt4(getUser().getUserCode());
                attach.setExt5(getUser().getUserDesc());
                attach.setSourceGuid(sourceGuid);
                attach.setSourceModel(sourceModel);
                attach.setFolderId("1");
                xtdcAttachService.insert(attach);

                Map<String, Object> map = new HashMap<>();
                map.put("sourceGuid", sourceGuid);
                map.put("sourceModel", sourceModel);
                map.put("fileId", attach.getId());
                map.put("filename", filename);
                map.put("fileSize", fileSize);
                map.put("relativePath", relativePath);
                list.add(map);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            log.error("文件上传失败！", e);
            return AjaxResult.error();
        }

        return AjaxResult.success("上传成功！", list);
    }

    @GetMapping("common/previewPDF")
    @ApiOperation("预览pdf")
    public void previewPDF(String fileName, String relativePath, String businessCode, HttpServletResponse response, HttpServletRequest request) {
        String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
        try {
            String filePath = ReadProperties.getValueString("projectServerFilePath");
            if (StringUtils.isNotEmpty(relativePath)) {
                filePath = filePath + "/" + relativePath + "/";
            }else{

            }
            //兼容老代码（待删除）
            if (StringUtils.isNotEmpty(businessCode)) {
                FileManager.Config config = fileManager.getConfig();
                config.setBusinessCode(businessCode);
                String dir = fileManager.generateDir(config);
                filePath = dir;
            }
            filePath += fileName;
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "inline; filename=" + setFileDownloadHeader(request, realFileName));
            FileUtils.writeBytes(filePath, response.getOutputStream());

        } catch (Exception e) {
            log.error("预览pdf失败", e);
        }
    }

    @PostMapping("common/downLoadZip")
    public void downLoadZipFile(@RequestBody List<ResourceVO> resourceVOList, HttpServletResponse response, HttpServletRequest request) throws IOException {
        String zipName = "资源文件.zip";
        String fileNameUUID = UUID.randomUUID().toString();
        try {
            if (redisLock.louck(zipName)) {
                String filePath = ReadProperties.getValueString("projectServerFilePath");
                File rootFile = new File(filePath + "/" + fileNameUUID+"/");
                String rootPath = "";
                if (rootFile.isDirectory()) {
                    rootPath = rootFile.getAbsolutePath();
                } else {
                    rootFile.mkdir();
                    rootPath = rootFile.getAbsolutePath();
                }
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=" + setFileDownloadHeader(request, zipName));
                for (ResourceVO r : resourceVOList) {
                    XtdcAttach xtdcAttach = attachMapper.selectByPrimaryKey(r.getId());
                    //如果是文件的话，首先创建文件
                    if (xtdcAttach != null) {
                        String fileName = org.apache.commons.lang.StringUtils.substringAfterLast(xtdcAttach.getFilePath(), "/");
                        File file = new File(rootPath + "/" + fileName);
                        File file1 = new File(xtdcAttach.getFilePath());
                        FileOutputStream fileOutputStream = new FileOutputStream(file);
                        Files.copy(file1, fileOutputStream);
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                    //如果是文件夹则创建文件夹
                    else {
                        File directory = new File(rootPath + "/" + r.getFileName());
                        directory.mkdir();
                        XtdcDirectory directoryQ = new XtdcDirectory();
                        directoryQ.setId(r.getId());
                        DirVO dirVO = directoryService.selectChildList(directoryQ);
                        //进入迭代方法
                        loopDir(dirVO, directory);
                    }
                }
                ZipUtils.toZip(rootPath, response.getOutputStream(), true);
                ZipUtils.deleteFolder(rootPath);
                redisLock.unLouck(zipName);
            }else {
                throw new RuntimeException("资源占用中！稍后请尝试");
            }
        } catch (Exception e) {
            throw new RuntimeException("打包下载出现问题，请联系管理员检查！");
        }
    }

    private void loopDir(DirVO dirVO, File file) throws IOException {
        List<XtdcAttach> attachList = dirVO.getAttachList();
        for (XtdcAttach attach : attachList) {
            String fileName = org.apache.commons.lang.StringUtils.substringAfterLast(attach.getFilePath(), "/");
            File file1 = new File(file.getAbsolutePath() + "/" + fileName);
            File file2 = new File(attach.getFilePath());
            FileOutputStream fileOutputStream = new FileOutputStream(file1);
            Files.copy(file2, fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();

        }
        List<XtdcDirectory> directoryList = dirVO.getDirectoryList();
        for (XtdcDirectory directory : directoryList) {
            File file1 = new File(file.getAbsolutePath() + "/" + directory.getDirName());
            file1.mkdir();
            XtdcDirectory directoryQ = new XtdcDirectory();
            directoryQ.setId(directory.getId());
            DirVO dirVO2 = directoryService.selectChildList(directoryQ);
            //进入迭代方法
            loopDir(dirVO2, file1);
        }
    }

}
